using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using LF.Domain.Entities;
using LF.Domain.Helper;
using Qdrant.Client;
using Qdrant.Client.Grpc;
// OpenXML
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Spreadsheet;
// PDF引用
using UglyToad.PdfPig;
using UglyToad.PdfPig.Content;
using static FreeSql.Internal.GlobalFilter;
using System.Text.RegularExpressions;
using DocumentFormat.OpenXml.Math;
using DocumentFormat.OpenXml.Wordprocessing;

namespace LF.Domain.Services.Iml
{
    public class AIService : IAIService
    {
        private readonly ITextEmbeddingService _embeddingService;
        private readonly IKnowledgeBaseManagerService _knowledgeBaseManager;
        private readonly IParamConfigManagerService _paramConfigManager;
        private readonly HttpClient _httpClient;
        
        public AIService(IParamConfigManagerService paramConfigManager,
            ITextEmbeddingService embeddingService,
            IKnowledgeBaseManagerService knowledgeBaseManager)
        {
            _paramConfigManager = paramConfigManager;
            _embeddingService = embeddingService;
            _knowledgeBaseManager = knowledgeBaseManager;
            _httpClient = new HttpClient();
        }
        
        /// <summary>
        /// 根据知识库生成文本向量嵌入
        /// </summary>
        public async Task<bool> GenerateEmbeddingsAsync(Guid knowledgeBaseId, Guid? fileId = null)
        {
            try
            {
                // 获取知识库
                var knowledgeBase = _knowledgeBaseManager.GetKnowledgeBase(knowledgeBaseId);
                if (knowledgeBase == null)
                    return false;
                
                // 如果指定了文件ID，则仅处理该文件
                if (fileId.HasValue)
                {
                    var file = _knowledgeBaseManager.GetKnowledgeFile(fileId.Value);
                    if (file == null || file.KnowledgeBaseId != knowledgeBaseId)
                        return false;
                    
                    bool success = await ProcessDocumentAsync(file.FileMD5, file.FileName+"."+file.Suffix, file.SliceType, file.FixedLength) > 0;
                    
                    if (success)
                    {
                        // 更新文件的IsEmbedding属性为true
                        file.IsEmbedding = true;
                        _knowledgeBaseManager.UpdateKnowledgeFile(file);
                    }
                    
                    return success;
                }
                
                // 处理知识库中的所有文件
                var files = _knowledgeBaseManager.GetKnowledgeFileList(1, 100, knowledgeBaseId, null, null);
                bool allSuccess = true;
                
                foreach (var file in files)
                {
                    bool success = await ProcessDocumentAsync(file.FileMD5, file.FileName + "." + file.Suffix, file.SliceType, file.FixedLength) > 0;
                    
                    if (success)
                    {
                        // 更新文件的IsEmbedding属性为true
                        file.IsEmbedding = true;
                        _knowledgeBaseManager.UpdateKnowledgeFile(file);
                    }
                    else
                    {
                        allSuccess = false;
                    }
                }
                
                return allSuccess;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"生成嵌入失败: {ex.Message}");
                return false;
            }
        }
        
        /// <summary>
        /// 分析文档并生成向量嵌入
        /// </summary>
        public async Task<int> ProcessDocumentAsync(string fileMD5, string filename, int sliceType, int? fixedLength = null)
        {
            try
            {
                // 获取文件内容
                var filePath = Path.Combine(DomainConfig.FilePath, fileMD5);
                if (!Directory.Exists(filePath))
                    return 0;
                
                // 读取文件内容
                var content = ReadFileContent(filePath, filename.Split(".")[1]);
                if (string.IsNullOrEmpty(content))
                    return 0;
                
                // 根据切片方式处理文本
                List<string> chunks = new List<string>();
                
                switch (sliceType)
                {
                    case 0: // 固定长度
                        int chunkSize = fixedLength.GetValueOrDefault(500);
                        chunks = SplitTextByLength(content, chunkSize);
                        break;
                    case 1: // QA问答
                        chunks = ExtractQAPairs(content);
                        break;
                    case 2: // 段落
                        chunks = SplitTextByParagraph(content);
                        break;
                    default:
                        return 0;
                }
                
                // 准备用于生成向量嵌入的内容
                List<string> embeddingTexts = new List<string>();
                if (sliceType == 1) // 对于QA问答类型，使用问题内容生成向量
                {
                    foreach (var chunk in chunks)
                    {
                        string question = "";
                        var lines = chunk.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                        foreach (var line in lines)
                        {
                            var trimmedLine = line.Trim();
                            if (trimmedLine.StartsWith("Q：") || trimmedLine.StartsWith("Q:") ||
                                trimmedLine.StartsWith("问：") || trimmedLine.StartsWith("问:") ||
                                trimmedLine.StartsWith("问题：") || trimmedLine.StartsWith("问题:") ||
                                trimmedLine.StartsWith("Question：") || trimmedLine.StartsWith("Question:"))
                            {
                                // 提取问题内容
                                question = ExtractContentAfterPrefix(trimmedLine);
                                break;
                            }
                        }
                        
                        // 如果找到了问题内容，使用它生成向量，否则使用整个块
                        embeddingTexts.Add(string.IsNullOrEmpty(question) ? chunk : question);
                    }
                }
                else // 对于其他类型，直接使用原始块
                {
                    embeddingTexts = chunks;
                }
                
                // 为每个分块生成嵌入
                var embeddings = await _embeddingService.GetEmbeddingsAsync(embeddingTexts);
                
                // 存储分块和嵌入
                await StoreChunksAndEmbeddingsAsync(chunks, embeddings, fileMD5, filename, sliceType);
                
                return chunks.Count;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"处理文档失败: {ex.Message}");
                return 0;
            }
        }
        #region 私有辅助方法
        
        private string ReadFileContent(string filePath,string extension)
        {
            try
            {
                var fileBytes = GetFileBytes(filePath);
                if (fileBytes == null || fileBytes.Length == 0)
                    return string.Empty;
                // 根据文件扩展名选择适当的解析方法
                switch (extension)
                {
                    case "docx":
                        return ParseDocxContent(fileBytes);
                    case "xlsx":
                        return ParseXlsxContent(fileBytes);
                    case "pptx":
                        return ParsePptxContent(fileBytes);
                    case "pdf":
                        return ParsePdfContent(fileBytes);
                    default:
                        // 对于纯文本文件，使用默认的文本转换
                        return BytesToText(fileBytes);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取文件内容失败: {ex.Message}");
                return string.Empty;
            }
        }
        
        /// <summary>
        /// 解析Word文档(.docx)内容
        /// </summary>
        private string ParseDocxContent(byte[] fileBytes)
        {
            using var stream = new MemoryStream(fileBytes);
            using var document = WordprocessingDocument.Open(stream, false);
            
            if (document.MainDocumentPart?.Document?.Body == null)
                return string.Empty;
                
            var textBuilder = new StringBuilder();
            var paragraphs = document.MainDocumentPart.Document.Body.Descendants<DocumentFormat.OpenXml.Wordprocessing.Paragraph>();
            
            foreach (var paragraph in paragraphs)
            {
                // 获取段落文本
                string paragraphText = paragraph.InnerText;
                
                // 只添加非空段落
                if (!string.IsNullOrWhiteSpace(paragraphText))
                {
                    textBuilder.AppendLine(paragraphText);
                    // 添加额外的换行确保段落间有清晰分隔
                    textBuilder.AppendLine();
                }
            }
            
            return textBuilder.ToString();
        }
        
        /// <summary>
        /// 解析Excel文档(.xlsx)内容
        /// </summary>
        private string ParseXlsxContent(byte[] fileBytes)
        {
            using var stream = new MemoryStream(fileBytes);
            using var document = SpreadsheetDocument.Open(stream, false);
            
            var textBuilder = new StringBuilder();
            var workbookPart = document.WorkbookPart;
            
            if (workbookPart == null)
                return string.Empty;
                
            foreach (var sheet in workbookPart.Workbook.Descendants<DocumentFormat.OpenXml.Spreadsheet.Sheet>())
            {
                var relationshipId = sheet.Id?.Value;
                if (string.IsNullOrEmpty(relationshipId))
                    continue;
                    
                var worksheetPart = (WorksheetPart)workbookPart.GetPartById(relationshipId);
                var sheetData = worksheetPart.Worksheet.Elements<SheetData>().First();
                
                foreach (var row in sheetData.Elements<Row>())
                {
                    foreach (var cell in row.Elements<Cell>())
                    {
                        string value = string.Empty;
                        
                        if (cell.DataType != null && cell.DataType == CellValues.SharedString)
                        {
                            var stringTable = workbookPart.SharedStringTablePart.SharedStringTable;
                            value = stringTable.Elements<SharedStringItem>().ElementAt(int.Parse(cell.InnerText)).InnerText;
                        }
                        else
                        {
                            value = cell.InnerText;
                        }
                        
                        textBuilder.Append(value);
                        textBuilder.Append("\t");
                    }
                    textBuilder.AppendLine();
                }
                textBuilder.AppendLine();
            }
            
            return textBuilder.ToString();
        }
        
        /// <summary>
        /// 解析PowerPoint文档(.pptx)内容
        /// </summary>
        private string ParsePptxContent(byte[] fileBytes)
        {
            using var stream = new MemoryStream(fileBytes);
            using var presentationDocument = PresentationDocument.Open(stream, false);
            
            var textBuilder = new StringBuilder();
            var presentationPart = presentationDocument.PresentationPart;
            
            if (presentationPart == null)
                return string.Empty;
                
            foreach (var slidePart in presentationPart.SlideParts)
            {
                foreach (var text in slidePart.Slide.Descendants<DocumentFormat.OpenXml.Drawing.Text>())
                {
                    textBuilder.Append(text.Text);
                    textBuilder.Append(" ");
                }
                textBuilder.AppendLine();
            }
            
            return textBuilder.ToString();
        }
        
        /// <summary>
        /// 解析PDF文档内容
        /// </summary>
        private string ParsePdfContent(byte[] fileBytes)
        {
            var textBuilder = new StringBuilder();
            
            using var stream = new MemoryStream(fileBytes);
            using var document = PdfDocument.Open(stream);
            
            for (var i = 1; i <= document.NumberOfPages; i++)
            {
                var page = document.GetPage(i);
                textBuilder.AppendLine(page.Text);
            }
            
            return textBuilder.ToString();
        }
        
        /// <summary>
        /// 将字节流转换为文本内容
        /// </summary>
        /// <param name="bytes">字节数组</param>
        /// <returns>文本内容</returns>
        private string BytesToText(byte[] bytes)
        {
            if (bytes == null || bytes.Length == 0)
                return string.Empty;
                
            try
            {
                // 尝试使用UTF8编码
                return Encoding.UTF8.GetString(bytes);
            }
            catch
            {
                try
                {
                    // 如果UTF8失败，尝试使用当前系统默认编码
                    return Encoding.Default.GetString(bytes);
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"转换字节流到文本失败: {ex.Message}");
                    return string.Empty;
                }
            }
        }
        
        /// <summary>
        /// 获取文件的字节数组
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>字节数组</returns>
        private byte[] GetFileBytes(string filePath)
        {
            try
            {
                var files = Directory.GetFiles(filePath).OrderBy(p => p);
                using MemoryStream stream = new MemoryStream();
                foreach (var chunk in files)
                {
                    if (string.IsNullOrEmpty(chunk)) continue;
                    using (var fs = new FileStream(chunk, FileMode.Open, FileAccess.Read, FileShare.Read))
                    {
                        var buffer = new byte[fs.Length];
                        fs.Read(buffer, 0, buffer.Length);
                        stream.Write(buffer, 0, buffer.Length);
                    }
                }
                stream.Seek(0, SeekOrigin.Begin);
                return stream.ToArray();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"获取文件字节失败: {ex.Message}");
                return Array.Empty<byte>();
            }
        }
        
        private List<string> SplitTextByLength(string text, int chunkSize)
        {
            var chunks = new List<string>();
            for (int i = 0; i < text.Length; i += chunkSize)
            {
                var length = Math.Min(chunkSize, text.Length - i);
                chunks.Add(text.Substring(i, length));
            }
            return chunks;
        }
        
        private List<string> ExtractQAPairs(string text)
        {
            // 实际项目中的QA提取逻辑更加复杂，包括以下几种情况：
            var chunks = new List<string>();
            
            // 1. 基于格式识别：处理明确标记的QA格式
            var formalQAPairs = ExtractFormalQAPairs(text);
            chunks.AddRange(formalQAPairs);
            
            // 2. 基于文本结构识别：处理FAQ风格但没有明确Q/A标记的内容
            if (formalQAPairs.Count == 0)
            {
                var structuredQAPairs = ExtractStructuredQAPairs(text);
                chunks.AddRange(structuredQAPairs);
            }
            
            //// 3. 基于语义分析：使用NLP模型进行问答对提取
            //if (chunks.Count == 0 && text.Length > 100)
            //{
            //    // 注意：这里简化实现，实际项目中可能需要调用LLM服务
            //    // var semanticQAPairs = ExtractSemanticQAPairs(text);
            //    // chunks.AddRange(semanticQAPairs);
                
            //    // 如果无法提取QA，则按段落拆分
            //    chunks.AddRange(SplitTextByParagraph(text));
            //}
            
            return chunks;
        }
        
        /// <summary>
        /// 提取正式格式化的QA对（例如明确的Q:/A:标记）
        /// </summary>
        private List<string> ExtractFormalQAPairs(string text)
        {
            var pairs = new List<string>();
            var lines = text.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.None);
            
            StringBuilder currentQA = null;
            bool inQuestion = false;
            bool inAnswer = false;
            
            foreach (var line in lines)
            {
                var trimmedLine = line.Trim();
                
                // 检测问题开始的各种格式
                bool isQuestionStart = trimmedLine.StartsWith("Q：") || trimmedLine.StartsWith("Q:") ||
                                       trimmedLine.StartsWith("问：") || trimmedLine.StartsWith("问:") ||
                                      trimmedLine.StartsWith("问题：") || trimmedLine.StartsWith("问题:") ||
                                      trimmedLine.StartsWith("Question：") || trimmedLine.StartsWith("Question:") ||
                                      Regex.IsMatch(trimmedLine, @"^\d+[\.\)、]\s*[a-zA-Z\u4e00-\u9fa5]");
                
                // 检测回答开始的各种格式
                bool isAnswerStart = trimmedLine.StartsWith("A：") || trimmedLine.StartsWith("A:") ||
                                    trimmedLine.StartsWith("答：") || trimmedLine.StartsWith("答:") ||
                                    trimmedLine.StartsWith("回答：") || trimmedLine.StartsWith("回答:") ||
                                    trimmedLine.StartsWith("Answer：")||trimmedLine.StartsWith("Answer:");
                
                if (isQuestionStart)
                {
                    // 如果之前已经有QA对，则保存
                    if (currentQA != null && inAnswer)
                    {
                        pairs.Add(currentQA.ToString().Trim());
                    }
                    
                    // 开始新的QA对
                    currentQA = new StringBuilder();
                    currentQA.AppendLine(trimmedLine);
                    inQuestion = true;
                    inAnswer = false;
                }
                else if (isAnswerStart && inQuestion)
                {
                    // 将回答添加到当前QA对
                    currentQA.AppendLine(trimmedLine);
                    inAnswer = true;
                }
                else if (currentQA != null)
                {
                    // 将文本行添加到当前QA对
                    currentQA.AppendLine(trimmedLine);
                }
            }
            
            // 添加最后一个QA对
            if (currentQA != null && inAnswer)
            {
                pairs.Add(currentQA.ToString().Trim());
            }
            
            return pairs;
        }
        
        /// <summary>
        /// 提取结构化的QA对（例如问句+回答段落）
        /// </summary>
        private List<string> ExtractStructuredQAPairs(string text)
        {
            var pairs = new List<string>();
            var paragraphs = SplitTextByParagraph(text);
            
            for (int i = 0; i < paragraphs.Count - 1; i++)
            {
                var current = paragraphs[i];
                var next = paragraphs[i + 1];
                
                // 检测当前段落是否像是问题（以问号结尾或包含典型的问句模式）
                if (current.EndsWith("?") || current.EndsWith("？") || 
                    current.Contains("如何") || current.Contains("什么") || 
                    current.Contains("为什么") || current.Contains("怎么"))
                {
                    // 构建QA对：将当前段落作为问题，下一段落作为答案
                    var qaPair = new StringBuilder();
                    qaPair.AppendLine($"Q: {current}");
                    qaPair.AppendLine($"A: {next}");
                    
                    pairs.Add(qaPair.ToString());
                    i++; // 跳过已使用的下一段落
                }
            }
            
            return pairs;
        }
        
        /// <summary>
        /// 使用语义分析提取QA对（实际项目中可能调用LLM服务）
        /// </summary>
        private List<string> ExtractSemanticQAPairs(string text)
        {
            // 这里是简化实现，实际项目中可能需要：
            // 1. 调用外部LLM服务生成可能的问题
            // 2. 使用NER识别关键实体，围绕实体生成问题
            // 3. 使用关键短语提取算法识别重要概念，生成相关问题
            
            // 简单示例：对较长文本段落，尝试提取主题并构建一个简单的QA对
            var pairs = new List<string>();
            
            var paragraphs = SplitTextByParagraph(text);
            foreach (var paragraph in paragraphs)
            {
                if (paragraph.Length > 100)
                {
                    // 提取前30个字符作为可能的主题
                    var topic = paragraph.Substring(0, Math.Min(30, paragraph.Length));
                    
                    // 构建QA对
                    var qaPair = new StringBuilder();
                    qaPair.AppendLine($"Q: 请解释{topic}的相关内容?");
                    qaPair.AppendLine($"A: {paragraph}");
                    
                    pairs.Add(qaPair.ToString());
                }
            }
            
            return pairs;
        }
        
        private List<string> SplitTextByParagraph(string text)
        {
            // 按段落分割文本
            return text.Split(new[] { "\r\n\r\n", "\n\n" }, StringSplitOptions.RemoveEmptyEntries)
                .Select(p => p.Trim())
                .Where(p => !string.IsNullOrEmpty(p))
                .ToList();
        }
        private string GetQrantUrl()
        {
            try
            {
                var config = _paramConfigManager.GetByKey("qdrant_url");
                return config?.Value ?? DomainConfig.QdrantConfig.Host;
            }
            catch
            {
                return DomainConfig.QdrantConfig.Host;
            }
        }
        /// <summary>
        /// 存储文档分块和向量嵌入
        /// </summary>
        private async Task StoreChunksAndEmbeddingsAsync(List<string> chunks, List<float[]> embeddings, string fileMD5, string filename, int chunkType)
        {
            try
            {
                // 获取文件所属的知识库
                var file = FreeSqlHelper.DbContext.Queryable<KnowledgeFile>()
                    .Where(f => f.FileMD5 == fileMD5)
                    .First();
                
                if (file == null)
                    return;
                
                var knowledgeBase = _knowledgeBaseManager.GetKnowledgeBase(file.KnowledgeBaseId);
                if (knowledgeBase == null)
                    return;
                
                // 知识库名称作为集合名称
                string collectionName = knowledgeBase.Name;
                
                try
                {
                    // 初始化Qdrant客户端
                    using var client = new QdrantClient(GetQrantUrl());
                    
                    // 检查集合是否存在，不存在则创建
                    try
                    {
                        var collection = await client.GetCollectionInfoAsync(collectionName);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine($"集合不存在，创建新集合: {ex.Message}");
                        // 集合不存在，创建新集合
                        var vectorSize = (uint)(embeddings.FirstOrDefault()?.Length ?? DomainConfig.QdrantConfig.VectorSize);
                        
                        await client.CreateCollectionAsync(
                            collectionName, 
                            new VectorParams { 
                                Size = vectorSize, 
                                Distance = Distance.Cosine 
                            }
                        );
                    }
                    
                    // 不再调用删除方法，而是确保使用相同的ID覆盖现有点
                    Console.WriteLine($"正在更新文件 '{filename}' 的向量数据...");
                    //var filter = CreateFilter(filters);
                    //var hits = await client.SearchAsync(collectionName, query.ToArray(), filter);

                    // 批量准备点数据
                    var points = new List<PointStruct>();
                    for (int i = 0; i < chunks.Count; i++)
                    {
                        string content = chunks[i];
                        string question = "";
                        string answer = "";
                        
                        // 对QA类型的内容进行特殊处理，提取问题和回答
                        if (chunkType == 1) // QA问答类型
                        {
                            var lines = content.Split(new[] { "\r\n", "\r", "\n" }, StringSplitOptions.RemoveEmptyEntries);
                            for (int j = 0; j < lines.Length; j++)
                            {
                                var line = lines[j].Trim();
                                
                                // 寻找问题行
                                if (line.StartsWith("Q：") || line.StartsWith("Q:") ||
                                    line.StartsWith("问：") || line.StartsWith("问:") ||
                                    line.StartsWith("问题：") || line.StartsWith("问题:") ||
                                    line.StartsWith("Question：") || line.StartsWith("Question:"))
                                {
                                    // 提取问题内容
                                    question = ExtractContentAfterPrefix(line);
                                }
                                // 寻找回答行
                                else if (line.StartsWith("A：") || line.StartsWith("A:") ||
                                        line.StartsWith("答：") || line.StartsWith("答:") ||
                                        line.StartsWith("回答：") || line.StartsWith("回答:") ||
                                        line.StartsWith("Answer：") || line.StartsWith("Answer:"))
                                {
                                    // 提取回答内容
                                    answer = ExtractContentAfterPrefix(line);
                                    
                                    // 如果后面还有行，将它们追加到回答中
                                    for (int k = j + 1; k < lines.Length; k++)
                                    {
                                        answer += "\n" + lines[k];
                                    }
                                    break;
                                }
                            }
                            
                            // 如果是QA类型且成功提取了回答，则content只存储回答部分
                            if (!string.IsNullOrEmpty(answer))
                            {
                                content = answer;
                            }
                        }
                        
                        // 使用文件ID和块索引作为ID，用于去重和覆盖
                        var fileId = file.Id.ToString();
                        var idBytes = Encoding.UTF8.GetBytes($"{fileId}_{i}");
                        var idHash = new SHA256Managed().ComputeHash(idBytes);
                        var pointId = BitConverter.ToUInt64(idHash, 0);
                        
                        var point = new PointStruct
                        {
                            Id = pointId,
                            Vectors = embeddings[i]
                        };
                        
                        // 添加Payload数据
                        point.Payload.Add("content", content);
                        point.Payload.Add("file_name", filename);
                        point.Payload.Add("file_md5", fileMD5);
                        point.Payload.Add("file_id", fileId);
                        point.Payload.Add("chunk_type", chunkType);
                        point.Payload.Add("chunk_order", i);
                        point.Payload.Add("timestamp", DateTime.UtcNow.ToString("o"));
                        
                        // 对QA类型额外存储问题信息
                        if (chunkType == 1 && !string.IsNullOrEmpty(question))
                        {
                            point.Payload.Add("question", question);
                        }
                        
                        points.Add(point);
                    }
                    
                    // 批量写入或更新Qdrant
                    await client.UpsertAsync(collectionName, points);
                    
                    Console.WriteLine($"成功更新文件 '{filename}' 的向量数据，共 {points.Count} 个向量");
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Qdrant操作异常: {ex.Message}");
                    throw;
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine($"存储文档分块和向量嵌入时发生错误: {ex.Message}");
                throw;
            }
        }
        
        /// <summary>
        /// 从前缀（如"Q:"、"A:"等）之后提取内容
        /// </summary>
        private string ExtractContentAfterPrefix(string line)
        {
            var colonIndex = line.IndexOf(':');
            if (colonIndex < 0)
                colonIndex = line.IndexOf('：');
                
            if (colonIndex >= 0 && colonIndex < line.Length - 1)
                return line.Substring(colonIndex + 1).Trim();
                
            return line;
        }
        private Qdrant.Client.Grpc.Filter CreateFilter(Dictionary<string, object>? filters)
        {
            var conditions = new List<Condition>();

            foreach (var filter in filters)
            {
                if (filter.Value is Dictionary<string, object> rangeDict &&
                    rangeDict.ContainsKey("gte") && rangeDict.TryGetValue("lte", out var value))
                {
                    conditions.Add(new Condition
                    {
                        Field = new FieldCondition()
                        {
                            Key = filter.Key,
                            Match = new Qdrant.Client.Grpc.Match
                            {
                                Text = value.ToString()
                            }
                        },
                    });
                }
                else
                {
                    conditions.Add(new Condition()
                    {
                        Field = new FieldCondition
                        {
                            Key = filter.Key,
                            Match = new Qdrant.Client.Grpc.Match
                            {
                                Text = filter.Value.ToString()
                            }
                        }
                    });
                }
            }

            var filterValue = new Qdrant.Client.Grpc.Filter()
            {
                Must =
            {
                conditions
            }
            };
            return conditions.Any() ? filterValue : null;
        }
        private class OllamaGenerateResponse
        {
            public string Response { get; set; }
        }
        
        #endregion
    }
} 